package com.goods.crawler.facade;

import com.goods.crawler.api.DTO.CrawlerRequestDTO;
import com.goods.crawler.entity.Product;
import com.goods.crawler.service.CategoryService;
import com.goods.crawler.service.IpTransferService;
import com.goods.crawler.service.ProductJDService;
import com.goods.crawler.service.ProductService;
import com.goods.crawler.utils.WebDriverFactory;
import org.openqa.selenium.*;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * <pre>类名: ProductFacade</pre>
 * <pre>描述: 爬虫Facade类</pre>
 * <pre>版权: 浙江理工大学信息学院</pre>
 * <pre>日期: 2019/1/21 15:25</pre>
 * <pre>作者: chenwb</pre>
 */
@Service
public class ProductFacade {

	private static Logger logger = LoggerFactory.getLogger(ProductFacade.class);

	@Autowired
	private ProductService productService;

	@Autowired
	private CategoryService categoryService;

	@Autowired
	private IpTransferService ipTransferService;

	@Autowired
	ProductJDService productJDService;

	/**
	 * @param crawlerRequestDTO
	 * @return void
	 * @Description: 爬取主流程入口
	 * @author chenwb
	 * @date 2019/1/21 15:25
	 */
	public void startCrawler(CrawlerRequestDTO crawlerRequestDTO) throws IOException {
		// 获取浏览器驱动
		WebDriver driver = WebDriverFactory.getInstance();
		//Set<Cookie> cookies = new HashSet<Cookie>();
		// 查询关键词
		List<String> keys = categoryService.findAllCategory();
		//boolean cookieFirst = true;
		while (true) {
			l:
			for (String key : keys) {
				//校验ip是否有效
/*				try {
					driver.get(crawlerRequestDTO.getUrl());
					new WebDriverWait(driver, 20).until(ExpectedConditions.presenceOfElementLocated(By.id("mallSearch")));
					driver.findElement(By.id("mallSearch"));
					logger.info("----------ip有效,可以继续爬取---------------");
				} catch (Exception e) {
					driver = ipTransferService.getNewInstance();
					driver.get(crawlerRequestDTO.getUrl()); //先请求页面
					driver.manage().deleteAllCookies();
					try {
						for (Cookie cookie : cookies) {
							driver.manage().addCookie(cookie);
						}
						driver.get(crawlerRequestDTO.getUrl()); //请求页面
					} catch (Exception e1) {
						e1.printStackTrace();
						logger.info("-----------cookie 添加失败-------------");
					}

				}*/
				try {
					// 提交关键词至搜索结果页
					this.basicOperation(crawlerRequestDTO, driver, key);
/*					if (cookieFirst) {
						cookies = driver.manage().getCookies();
						cookieFirst = false;
					}*/

					// 爬取搜索结果信息
					this.keyCrawler(driver, key);
					while (true) {
						// 等待回到原来搜索结果页
						new WebDriverWait(driver, 20).until(ExpectedConditions.presenceOfElementLocated(By.className("productImg-wrap")));
						int curPage = productService.getCurPageNum(driver);
						int pageTotal = productService.getPageTotal(driver);
						// 非末页，则点击下一页
						if (pageTotal >= curPage) {
							productService.toNextPage(driver);
							new WebDriverWait(driver, 20).until(ExpectedConditions.presenceOfElementLocated(By.className("productImg-wrap")));
							if (curPage == productService.getCurPageNum(driver)) {
								continue l;
							}
							new WebDriverWait(driver, 20).until(ExpectedConditions.presenceOfElementLocated(By.className("productImg-wrap")));
							this.keyCrawler(driver, key);
						} else {
							continue l;
						}
					}
				} catch (Exception e) {
					//不做处理
					e.printStackTrace();
				}

			}
		}

	}

	/**
	 * @param driver
	 * @param key
	 * @return void
	 * @Description: 爬取某个关键词的搜索结果
	 * @author chenwb
	 * @date 2019/1/23 15:22
	 */
	public void keyCrawler(WebDriver driver, String key) {
		new WebDriverWait(driver, 20, 3000).until(ExpectedConditions.presenceOfElementLocated(By.className("productImg-wrap")));
		// 获取搜索结果页当页数据
		List<WebElement> searchResults = ((FirefoxDriver) driver).findElementsByClassName("productImg-wrap");
		// 获取当前url，便于当页数据爬完后返回
		String curUrl = driver.getCurrentUrl();
		List<String> urls = new ArrayList<String>();
		for (WebElement element : searchResults) {
			urls.add(element.findElement(By.tagName("a")).getAttribute("href"));
		}
		// 对当页商品进行爬取
		for (String url : urls) {
			Product product = productService.crawlingOne(driver, url);
			Product productTemp = productService.findProductByProductId(product.getProductId());
			productService.saveProductInfo(product, productTemp, key);
		}
		// 回到搜索结果页
		driver.get(curUrl);
	}

	/**
	 * @param crawlerRequestDTO
	 * @return WebDriver
	 * @Description: 获取关键词查询，并返回driver
	 * @author chenwb
	 * @date 2019/1/23 14:54
	 */
	private WebDriver basicOperation(CrawlerRequestDTO crawlerRequestDTO, WebDriver driver, String key) {
		//driver.manage().window().maximize();
		// 隐性等待
		driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
		driver.get(crawlerRequestDTO.getUrl());
		// 判断是否登录 会被检测window.navigator.webdriver为true，无法登陆
/*
		new WebDriverWait(driver, 20).until(ExpectedConditions.presenceOfElementLocated(By.className("sn-register")));
		try {
			if (driver.findElement(By.className("sn-register")) != null) {
				driver.findElement(By.className("sn-login")).click();
				try {
					Thread.sleep(1000);
					driver.switchTo().frame("J_loginIframe");
					Thread.sleep(20);
					new WebDriverWait(driver, 20).until(ExpectedConditions.presenceOfElementLocated(By.id("TPL_username_1")));
					try {
						driver.findElement(By.id("TPL_username_1")).clear();
						driver.findElement(By.id("TPL_username_1")).sendKeys("我叫陈伟标44");
					} catch (Exception e) {
						driver.findElement(By.id("J_Quick2Static")).click();
						driver.findElement(By.id("TPL_username_1")).sendKeys("我叫陈伟标44");
					}
					driver.findElement(By.id("TPL_password_1")).clear();
					driver.findElement(By.id("TPL_password_1")).sendKeys("xiaoshagua11.21");
					Thread.sleep(20);
					driver.findElement(By.id("J_SubmitStatic")).click();
					Thread.sleep(20);
					try{
						if(driver.findElement(By.className("error"))!=null){
							Thread.sleep(1000);
							driver.findElement(By.id("TPL_username_1")).clear();
							driver.findElement(By.id("TPL_username_1")).sendKeys("我叫陈伟标44");
							Thread.sleep(1000);
							driver.findElement(By.id("TPL_password_1")).sendKeys("xiaoshagua11.21");
							Thread.sleep(1000);
							//JavascriptExecutor executor = (JavascriptExecutor)driver;
							WebElement element = driver.findElement(By.id("nc_1_n1z"));
							Point location = element.getLocation();
							Actions action = new Actions(driver);
							action.dragAndDropBy(element, location.x+258,location.y).perform();
							Thread.sleep(1000);
							driver.findElement(By.id("J_SubmitStatic")).click();
						}
					}catch (Exception e){
						//no operate
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
*/

		new WebDriverWait(driver, 20).until(ExpectedConditions.presenceOfElementLocated(By.className("s-combobox-input")));
		// 输入关键词
		WebElement inputelement = driver.findElement(By.className("s-combobox-input"));
		inputelement.sendKeys(key);
		// 表单提交
		WebElement searchTop = driver.findElement(By.name("searchTop"));
		searchTop.submit();
		return driver;
	}

	/**
	 * @return void
	 * @Description: 补充爬取
	 * @author chenwb
	 * @date 2019/2/20 15:36
	 */
	public void additionCrawler() {
		List<Product> products = productService.findAllProducts();
		WebDriver driver1 = WebDriverFactory.getInstance();
		WebDriver driver2 = WebDriverFactory.getInstance();
		Product product1 = null;
		for (Product product : products) {

			if ("1".equals(product.getSpareField2()) || StringUtils.isEmpty(product.getSpareField2())) {
				try {
					product1 = productService.crawlingOne(driver1, product.getProductUrl());
					Product productTemp = productService.findProductByProductId(product1.getProductId());
					productService.saveProductInfoAdd(product1, productTemp, "1");
				} catch (Exception e) {
					continue;
				}
			} else if ("2".equals(product.getSpareField2())) {
				try {
					product1 = productJDService.crawlingOne(driver2, product.getProductUrl());
					Product productTemp = productService.findProductByProductId(product1.getProductId());
					productService.saveProductInfoAdd(product1, productTemp, "2");
				} catch (Exception e) {
					continue;
				}
			}

		}
	}
}
